<?php

namespace app\admin\service;

use app\admin\dao\TransactionDao;
use app\admin\model\UM as UM;
use app\admin\traits\AdminCheckTrait;
use app\common\model\Member;
use app\common\model\Role;
use app\common\model\User;
use app\common\service\AccountBillService;
use app\common\service\TransfersServer;
use ShidianUtil\Utils\StringUtil;
use think\exception\ValidateException;

/**
 * Class TransactionService
 * @package app\admin\service
 */
class TransactionService
{
    use AdminCheckTrait;

    // dao
    protected TransactionDao $transactionDao;

    public function __construct(TransactionDao $transactionDao)
    {
        $this->transactionDao = $transactionDao;
    }

    /**
     * 充值记录
     * @param UM $user
     * @param $type
     * @param $companyId
     * @param $startTime
     * @param $endTime
     * @param int|null $page
     * @param int|null $page_size
     * @return array
     */
    public function index(UM $user, $type, $companyId, $startTime, $endTime, ?int $page = null, ?int $page_size = null): array
    {

        if (StringUtil::equals($type, 'company')) {
            if (StringUtil::equals($user->roleType, Role::ROLE_TYPE_COMPANY)) {
                $companyId = $user->id;
            }

            return $this->transactionDao->listTransactionOfCompany($companyId, $startTime, $endTime, $page, $page_size);
        }

        if (StringUtil::equals($type, 'member')) {
            if (StringUtil::equals($user->roleType, Role::ROLE_TYPE_COMPANY)) {
                throw new ValidateException('您不能查看用户充值数据');
            }

            return $this->transactionDao->listTransactionOfMember($startTime, $endTime, $page, $page_size);
        }

        throw new ValidateException('请选择公司或用户数据');
    }

    /**
     * 新增
     * @param UM $user
     * @param array $params
     * @return  void
     */
    public function add(UM $user, array $params): void
    {
        $userId = $user->id;
        $companyId = $params['companyId'] ?? null;
        $memberId = $params['memberId'] ?? null;
        $describe = $params['describe'] ?? null;

        $amount0 = $params['amount0'] ?? null;
        $total0 = $params['total0'] ?? null;
        $amount1 = $params['amount1'] ?? null;
        $total1 = $params['total1'] ?? null;

        $fromId = '0';
        $fromType = '';

        $this->checkAdmin($user);

        if (is_id($companyId)) {
            $fromId = $companyId;
            $fromType = 'company';
            $memberId = '0';

            $company = User::where('id', $companyId)->where('roleType', Role::ROLE_TYPE_COMPANY)->find();
            if (!$company) {
                throw new ValidateException('该公司不存在或已被删除');
            }

        } elseif ($memberId) {
            $fromId = $memberId;
            $fromType = 'member';
            $companyId = '0';

            $member = Member::where('id', $memberId)->whereIn('status', [0, 1])->find();
            if (!$member) {
                throw new ValidateException('该用户不存在或已被删除');
            }
        } else {
            throw new ValidateException('请选择充值的公司或用户');
        }


        $card = false;
        if (not_blank($total0)) {
            $card = true;
        }

        $coin = false;
        if (not_blank($total1)) {
            $coin = true;
        }

        if (!$card && !$coin) {
            throw new ValidateException('请输入要充值的获客卡和通信币数量');
        }

        if ($card) {
            $name = '获客卡';
            $accountType = PAYMENT_CARD;
            $billType = TRADE_OFFLINE_CARD_RECHARGE;
            $amount = $amount0;
            $total = $total0;

            $this->handle($amount, $total, $describe, $userId, $companyId, $memberId, $fromType, $fromId, $name, $accountType, $billType);
        }

        if ($coin) {
            $name = '通信币';
            $accountType = PAYMENT_COIN;
            $billType = TRADE_OFFLINE_COIN_RECHARGE;
            $amount = $amount1;
            $total = $total1;

            $this->handle($amount, $total, $describe, $userId, $companyId, $memberId, $fromType, $fromId, $name, $accountType, $billType);
        }
    }

    /**
     *
     * @param $amount
     * @param $total
     * @param $describe
     * @param $userId
     * @param $companyId
     * @param $memberId
     * @param $fromType
     * @param $fromId
     * @param string $name
     * @param $accountType
     * @param $billType
     * @return void
     */
    private function handle($amount, $total, $describe, $userId, $companyId, $memberId, $fromType, $fromId, string $name, $accountType, $billType): void
    {

        // 到账金额
        if (!is_numeric($total)) {
            throw new ValidateException('请输入正确的' . $name . '数量');
        }
        $total = round($total, 2);

        // 付款金额
        if (!is_numeric($amount)) {
            throw new ValidateException('请输入正确的' . $name . '充值金额');
        }
        $amount = round($amount, 2);

        // 备注
        if (is_blank($describe)) {
            throw new ValidateException('请输入备注信息');
        }

        // 校验
        if ($total == 0) {
            throw new ValidateException($name . '到账数量不能为0');
        }
        if ($total < 0 && $amount > 0) {
            throw new ValidateException($name . '到账数量是正数时，充值金额也应该是正数');
        }
        if ($total > 0 && $amount < 0) {
            throw new ValidateException($name . '到账数量是负数时，充值金额也应该是负数');
        }

        $this->handleTransfer($amount, $total, $describe, $userId, $companyId, $memberId, $accountType, $fromType, $fromId, $billType);

    }

    protected function handleTransfer($amount, $total, $describe, $userId, $companyId, $memberId, $accountType, string $fromType, $fromId, string $billType): void
    {
        $params = [];
        $params['userId'] = $userId;
        $params['companyId'] = $companyId;
        $params['memberId'] = $memberId;
        $params['amount'] = $amount;
        $params['total'] = $total;
        $params['accountType'] = $accountType;
        $params['describe'] = $describe;

        $transaction = $this->transactionDao->insertActive($params, []);
        $transactionId = $transaction->id;

        // 插入线下转账付款账单

        // 有付款金额
        if ($amount > 0) {
            $this->getAccountBillService()->insertTransferOffline(true, $fromType, $fromId, abs($amount), $billType, $describe, $transactionId);
        }
        // 有退款金额
        if ($amount < 0) {
            $this->getAccountBillService()->insertTransferOffline(false, $fromType, $fromId, abs($amount), $billType, $describe, $transactionId);
        }


        // 添加充值转账申请

        $transferType = '';

        if (StringUtil::equals($accountType, TRANSFER_COIN)) {
            $transferType = TRANSFER_COIN_RECHARGE;
        }

        if (StringUtil::equals($accountType, TRANSFER_CARD)) {
            $transferType = TRANSFER_CARD_RECHARGE;
        }

        if (StringUtil::equals($accountType, TRANSFER_MARGIN)) {
            $transferType = TRANSFER_MARGIN_RECHARGE;
        }

        // 有充值金额
        if ($total > 0) {
            $this->createTransfer($fromId, $fromType, $accountType, $transferType, abs($total), $describe, $transactionId);
        }
        // 充值负数
        if ($total < 0) {
            $this->createTransferReverse($fromId, $fromType, $accountType, $transferType, abs($total), $describe, $transactionId);
        }
    }

    /**
     * 创建转账申请
     * @param $toId
     * @param $toType
     * @param $accountType
     * @param $transferType
     * @param $total
     * @param $describe
     * @param $transactionId
     * @return void
     */
    private function createTransfer($toId, $toType, $accountType, $transferType, $total, $describe, $transactionId)
    {
        $payMethod = $accountType;
        $accountNumber = $toId;

        $append = [
            'transactionId' => $transactionId,
        ];

        if (StringUtil::equals($toType, 'member')) {
            $this->getTransfersServer()->pushTransferToMember($transferType, $toId, $payMethod, $accountNumber, $total, $describe, $append);
        }

        if (StringUtil::equals($toType, 'company')) {
            $this->getTransfersServer()->pushTransferToCompany($transferType, $toId, $payMethod, $accountNumber, $total, $describe, $append);
        }
    }

    /**
     * 创建反向转账申请
     * @param $fromId
     * @param $fromType
     * @param $accountType
     * @param $transferType
     * @param $total
     * @param $describe
     * @param $transactionId
     * @return void
     */
    private function createTransferReverse($fromId, $fromType, $accountType, $transferType, $total, $describe, $transactionId)
    {

        $payMethod = $accountType;
        $accountNumber = $fromId;

        $append = [
            'transactionId' => $transactionId,
        ];

        if (StringUtil::equals($fromType, 'member')) {
            $this->getTransfersServer()->pushTransferFromMember($transferType, $fromId, $payMethod, $accountNumber, $total, $describe, $append);
        }

        if (StringUtil::equals($fromType, 'company')) {
            $this->getTransfersServer()->pushTransferFromCompany($transferType, $fromId, $payMethod, $accountNumber, $total, $describe, $append);
        }
    }


    private function getAccountBillService(): AccountBillService
    {
        return app(AccountBillService::class);
    }

    private function getTransfersServer(): TransfersServer
    {
        return app(TransfersServer::class);
    }

}
